/*
 * @Author: Wang Xiao
 * @Date: 2017-05-09 20:46:50
 * @Last Modified by: Wang Xiao
 * @Last Modified time: 2017-06-06 16:11:39
 */

import { Base64 } from "js-base64";
import ios from "./ios";
import android from "./android";
import storage from "@/libs/storage";

class Hybrid {
  constructor(platform) {
    this.app = platform;
    this.driverMap = {
      ios,
      android,
    };

    try {
      this.driver = this.driverMap[platform];
    } catch (error) {
      console.error("Hybrid only support ios or android");
    }

    this.callbackFuncs = {}; // 协议注册回调
    this.callbackContent = {}; // App 注入的 callback 数据
    this.exposeToApp(); // 把方法暴露给 App
  }

  /**
   * 调用协议方法
   *
   * @param {any} actionName 协议方法名
   * @param {any} params 协议参数，json形式
   *
   * @memberof Proxy
   */
  action(actionName, params) {
    let obj = params;
    if (actionName === "ee") {
      const user = storage.get("user") || {};
      const isBasicType =
        (typeof obj.value === "string" || typeof obj.value === "number") &&
        obj.value;
        params = {
          content: {
            eventName: obj.content,
            eventValue: Object.assign(
              {
                packagename: "com.thrift.more",
                appname: "MoreGold",
                userid: user.userId || "",
              },
              isBasicType ? { value: obj.value } : obj.value
            ),
          },
        };
    }
    const callback = params && params.callback;
    let st = Math.random().toString();
    st = st.substr(2, st.length);

    // const callbackName = `${actionName}${st}`;
    const callbackName = `${actionName}`;

    // callback 如果存在callback 执行
    if (callback) {
      this.registerCB(callbackName, callback);
      params.callback = callbackName;
    }

    // 判断是否有特定方法，不存在则调用通用方法
    if (this.driver[actionName]) {
      this.driver[actionName](params, this);
    } else {
      try {
        this.driver.action(actionName, params, this);
      } catch (error) {
        console.error(`Action ${actionName} does not exist!`);
      }
    }
  }

  /**
   * 注册回调
   *
   * @param {any} callbackName 回调名字
   * @param {any} callback 回调函数
   *
   * @memberof Proxy
   */
  registerCB(callbackName, callback) {
    if (callback) {
      if (typeof callback === "function") {
        callback = {
          success: callback,
        };
      }

      callback = Object.assign(
        {},
        {
          success: () => {},
          error: () => {},
        },
        callback
      );
    }
    this.callbackFuncs[callbackName] = callback;
  }

  /**
   * 暴露给app的js方法
   * @memberof Proxy
   */
  exposeToApp() {
    window.setCallBackContent = (func, index, partten) => {
      if (!this.callbackContent[func]) {
        this.callbackContent[func] = {
          count: 0,
          data: {},
        };
      }
      this.callbackContent[func].count++;
      this.callbackContent[func].data[parseInt(index, 10)] = partten;
    };

    window.callback = (func, data, codec) => {
      function decode(text) {
        text = Base64.decode(text);
        text = decodeURIComponent(text);

        return text.replace(/\[:space\]/g, " ");
      }

      if (!data && this.callbackContent[func]) {
        // 通过分片调用
        const arr = [];
        for (let i = 0; i < this.callbackContent[func].count; i++) {
          arr.push(this.callbackContent[func].data[i]);
        }
        data = arr.join("");
      }

      if (codec === "base64") {
        /**
         * Encoder/decoder flag bit to indicate using the "URL and
         * filename safe" variant of Base64 (see RFC 3548 section 4) where
         * {@code -} and {@code _} are used in place of {@code +} and
         * {@code /}.
         */
        const text = data
          .replace(/-/g, "+")
          .replace(/_/g, "/")
          .replace(/\$/g, "=");
        try {
          data = decode(text);
        } catch (error) {
          data = {
            status: "0",
            error: "-1",
            message: error.message,
            data: {},
          };
        }
      }
      this.callback(func, data);
    };
  }

  /**
   * 函数回调
   *
   * @param {any} func
   * @param {any} data
   *
   * @memberof Proxy
   */
  callback(func, data) {
    if (typeof data !== "object" && data) {
      try {
        data = JSON.parse(data);
      } catch (e) {
        console.error(e);
      }
    }
    if (!this.callbackFuncs[func]) {
      console.error("Can't find callback function for this action");
      return;
    }

    if (data.status === "1" || data.status === 1) {
      this.callbackFuncs[func].success(data);
    } else {
      this.callbackFuncs[func].error(data);
    }
  }
}

export default Hybrid;
